﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Permissions;
using Dtf.Core.Remoting;

namespace Dtf.Core.Resources
{
    public class ResourceManager : RemotingObject
    {
        /// <summary>
        /// registerDefaultProvider = true
        /// </summary>
        public ResourceManager()
            : this(true)
        {
        }

        public ResourceManager(bool registerDefaultProvider)
        {
            _resourceProviders = new List<ResourceProvider>();
            
            _resourcePaths = "";

    /* "CTMenuString", "HTMLString", "INFString", "ManagedString", _
                     "MessageString", "MsiString", "NativeMenuString", "OfficeString", "SdmDialogString", _
                     "Win32DialogItemString", "Win32DialogString", "Win32String", "ManagedCTMenuString"
     */
            if (registerDefaultProvider)
            {
                _resourceProviders.Add(new Win32StringProvider("Win32String"));
                _resourceProviders.Add(new Win32MenuProvider("NativeMenuString"));
                _resourceProviders.Add(new Win32DialogProvider("Win32DialogString"));
                //_resourceProviders.Add(new Win32DialogItemProvider("Win32DialogItemString"));
            }
        }

        public void RegisterResourceProvider(ResourceProvider provider)
        {
            if (_resourceProviders.Contains(provider))
            {
                //LogManager.Write("ResourceProvider with 
            }
            _resourceProviders.Add(provider);
        }


        /// <summary>
        /// Resource key from RPF Recorder ;&Edit;NativeMenuString;notepad.exe;1;2p
        /// </summary>
        /// <param name="resourceId"></param>
        /// <returns></returns>
        public virtual string ExtractString(string resourceKey)
        {
            string[] keys = resourceKey.Split(new char[]{resourceKey[0]}, StringSplitOptions.RemoveEmptyEntries);
            if (keys.Length < 4)
            {
                throw new ResourceKeyException();
            }

            string resourceType = keys[1];
            if (!IsSupportedResource(resourceType))
            {
                throw new NotSupportedException("Not Supported Resource Type: " + resourceType);
            }

            string[] tokens = new string[keys.Length - 3];
            for(int i=0;i<tokens.Length;i++)
            {
                tokens[i] = keys[i+3];
            }

            foreach (ResourceProvider provider in _resourceProviders)
            {
                if (provider.ResourceTypeName == resourceType)
                {
                    string[] filePaths = GetFilesFullPaths(keys[2]);
                    if (filePaths.Length > 1)
                    {
                        LogManager.Write("More then one resource file have same name, search all", "red");
                    }
                    foreach (string filePath in filePaths)
                    {
                        string str = provider.ExtractString(filePath, tokens);
                        if (str != null)
                        {
                            return str;
                        }
                    }
                }
            }

            return null;

        }

        private bool IsSupportedResource(string resourceType)
        {
            foreach (ResourceProvider provider in _resourceProviders)
            {
                if (provider.ResourceTypeName == resourceType)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Retrive full path of resource file base on gived filename. (LCLang.dll)
        /// </summary>
        /// <param name="resFile"></param>
        /// <returns></returns>
        private string[] GetFilesFullPaths(string relFile)
        {
            
            string[] paths = ResourceSearchPaths.Split(new char[]{'|'}, StringSplitOptions.RemoveEmptyEntries);
            List<string> searchRet = new List<string>();
            foreach (string path in paths)
            {
                
                FileAttributes attr = File.GetAttributes(path);

                if (FileAttributes.Directory == (attr & FileAttributes.Directory))
                {
                    searchRet.AddRange(Directory.GetFiles(path, relFile, SearchOption.TopDirectoryOnly));
                }
                else
                {
                    if (Path.GetFileName(path).Equals(relFile.ToLower()))
                    {
                        searchRet.Add(path);
                    }
                }
            }
            return searchRet.ToArray(); ;
        }



        /// <summary>
        /// SearchPaths: c:\program files|c:\test.dll delimited by |.
        /// </summary>
        public string ResourceSearchPaths
        {
            get
            {
                return _resourcePaths;
            }
            set
            {
                _resourcePaths = value;
            }
        }

        public enum ResourceType
        {
            RT_STRING
        }

        private string _resourcePaths;
        private List<ResourceProvider> _resourceProviders;
        //private List<string> _resourcePaths;
    }
}
